package service

import (
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/shopspring/decimal"
	"gorm.io/gorm"
	"mojieshi/define"
	"mojieshi/models"
	"net/http"
	"time"
)

type Login struct {
	Code       string `json:"code"`
	AppId      int    `json:"app_id"`
	InviteCode string `json:"invite_code"`
	AppType    string `json:"app_type"`
	UserName   string `json:"user_name"` //姓名
	UserPic    string `json:"user_pic"`  //头像
}

/*微信小程序登录 返回值*/
type WXLoginResp struct {
	OpenId     string `json:"openid"`
	SessionKey string `json:"session_key"`
	UnionId    string `json:"unionid"`
	ErrCode    int    `json:"errcode"`
	ErrMsg     string `json:"errmsg"`
	Token      string `json:"token"`
	Auth       uint32 `json:"auth"`
	Name       string `json:"name"`
	Phone      string `json:"phone"`
	Nickname   string `json:"nickname"`  //微信昵称
	Headimage  string `json:"headimage"` //微信头像
}

// 获取微信小程序接口调用凭据
type WXAccessToken struct {
	AccessToken string `json:"access_token"`
	ExpiresIn   int    `json:"expires_in"`
}

/*抖音小程序登录 返回值*/
type DYloginResp struct {
	ErrNo   int    `json:"err_no"`
	ErrTips string `json:"err_tips"`
	Data    struct {
		SessionKey      string `json:"session_key"`
		Openid          string `json:"openid"`
		AnonymousOpenid string `json:"anonymous_openid"`
		Unionid         string `json:"unionid"`
	} `json:"data"`
}

// 小程序登入
func WXlogin(c *gin.Context) {
	var jsonData Login
	err := c.ShouldBindJSON(&jsonData)
	if err != nil {
		define.Response.ResultFail(c, 10000, define.JsonData, "")
		return
	}
	tx := models.DB.Begin() //开启事务
	//获取appid和密钥
	var appData models.AppCate
	err = tx.Model(new(models.AppCate)).Where("app_type=? AND id=?", jsonData.AppType, jsonData.AppId).First(&appData).Error
	if err != nil {
		define.Response.ResultFail(c, 10001, err.Error(), "")
		return
	}
	//拼接发起的url链接
	url := ""
	// 解析http请求中body 数据到我们定义的结构体中
	OpenId := ""
	UnionId := ""
	url = "https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code"
	// 合成url, 这里的appId和secret是在微信公众平台上获取的
	url = fmt.Sprintf(url, appData.AppId, appData.AppSecret, jsonData.Code)
	// 创建http get请求
	resp, err := http.Get(url)
	if err != nil {
		define.Response.ResultFail(c, 10002, err.Error(), "")
		return
	}
	defer resp.Body.Close()
	decoder := json.NewDecoder(resp.Body)
	wxResp := WXLoginResp{}
	err = decoder.Decode(&wxResp)
	if err != nil {
		define.Response.ResultFail(c, 10003, err.Error(), "")
		return
	}
	// 判断微信接口返回的是否是一个异常情况
	if wxResp.ErrCode != 0 {
		define.Response.ResultFail(c, 10004, wxResp.ErrMsg, "")
		return
	}
	OpenId = wxResp.OpenId
	UnionId = wxResp.UnionId
	fmt.Println("unionId", UnionId)

	//定义接收列表数据的切片
	var listBind []models.MUserBind
	//定义返回条数
	var count int64
	err = tx.Model(new(models.MUserBind)).Where("open_id=? AND app_type=?", OpenId, jsonData.AppType).Count(&count).Find(&listBind).Error
	if err != nil {
		define.Response.ResultFail(c, 10005, err.Error(), "")
		return
	}
	//token的原始
	var tokenData = make(map[string]interface{})
	logintoken := ""
	logInviteCode := ""
	logCity := ""
	logArea := ""
	Latitude := ""
	Longitude := ""
	//判断是否有数据，如果有就不需要注册，没有则登入
	if count <= 0 {
		var userBind models.MUserBind
		userBind.OpenId = OpenId
		userBind.Type = jsonData.AppId
		userBind.UnionID = UnionId
		userBind.AppType = jsonData.AppType
		//如果是新用户未在小程序注册过,立即注册
		userId, inviteCode, err := Register(tx, jsonData.InviteCode, jsonData.AppId, jsonData.AppType, OpenId)
		if err != nil {
			define.Response.ResultFail(c, 10008, err.Error(), "")
			tx.Rollback() //回滚事务
			return
		}
		logInviteCode = inviteCode
		//生成token
		token, err := define.GenerateToken(userId, "18711111111")
		if err != nil {
			define.Response.ResultFail(c, 10009, err.Error(), "")
			tx.Rollback() //回滚事务
			return
		}
		logintoken = token
		//存入token
		tokenData["token"] = token
		tokenData["last_visittime"] = time.Now().Unix()
		tokenData["today_huo"] = 1
		err = tx.Model(new(models.MMember)).Where("id=?", userId).Select("token", "login_at", "today_huo").Updates(tokenData).Error
		if err != nil {
			c.JSON(http.StatusOK, gin.H{
				"code": 10010,
				"msg":  err.Error(),
			})
			tx.Rollback() //回滚事务
			return
		}
		userBind.UserId = userId
		//写入userbind的数据
		err = tx.Model(new(models.MUserBind)).Create(&userBind).Error
		if err != nil {
			define.Response.ResultFail(c, 10011, err.Error(), "")
			tx.Rollback() //回滚事务
			return
		}
	} else {
		if listBind[0].UnionID == "" {
			err = tx.Model(new(models.MUserBind)).Where("open_id=? AND app_type=?", OpenId, jsonData.AppType).Update("union_id", UnionId).Error
			if err != nil {
				define.Response.ResultFail(c, 20001, err.Error(), "")
				return
			}
		}
		//登入
		//获取会员信息
		var userData models.MMember
		err = tx.Model(new(models.MMember)).Where("id=?", listBind[0].UserId).First(&userData).Error
		if err != nil {
			define.Response.ResultFail(c, 100012, err.Error(), "")
			tx.Rollback() //回滚事务
			return
		}
		//生成token
		token, err := define.GenerateToken(listBind[0].UserId, "18711111111")
		if err != nil {
			c.JSON(http.StatusOK, gin.H{
				"code": 100013,
				"msg":  "Token生成失败",
			})
			tx.Rollback() //回滚事务
			return
		}
		logintoken = token
		logInviteCode = userData.InviteCode
		logCity = userData.City
		logArea = userData.Area
		Latitude = userData.Latitude
		Longitude = userData.Longitude
		tokenData["token"] = token
		tokenData["last_visittime"] = time.Now().Unix()
		tokenData["today_huo"] = 1
		err = tx.Model(new(models.MMember)).Where("id=?", listBind[0].UserId).Select("token", "login_at", "today_huo").Updates(tokenData).Error
		if err != nil {
			c.JSON(http.StatusOK, gin.H{
				"code": 100014,
				"msg":  err.Error(),
			})
			tx.Rollback() //回滚事务
			return
		}
	}
	tx.Commit() //结束事务
	c.JSON(http.StatusOK, gin.H{
		"code": 0,
		"msg":  "登入成功！",
		"data": map[string]interface{}{
			"token":       logintoken,
			"user_id":     listBind[0].UserId,
			"invite_code": logInviteCode,
			"city":        logCity,
			"area":        logArea,
			"latitude":    Latitude,
			"longitude":   Longitude,
		},
	})
}

// 用户注册
func Register(tx *gorm.DB, inviteCode string, appId int, appType string, OpenId string) (int, string, error) {
	var parId models.MMember
	var count int64
	//查询上级id
	fmt.Println(inviteCode)
	tx.Model(new(models.MMember)).Where("invite_code=?", inviteCode).Count(&count).First(&parId)
	if count == 0 {
		parId.ID = 0
	}
	var userData = map[string]interface{}{
		"community_sum": parId.CommunitySum + 1,
	}
	err := tx.Model(new(models.MMember)).Where("id=?", parId.ID).Updates(&userData).Error
	if err != nil {
		tx.Rollback()
		return 0, "", err
	}

	//生成MD5密码
	myPassword := define.GetMD5("123456")
	//生成邀请码
	var inviteCode1 string
	for i := 0; i < 99; i++ {
		inviteCode1 = string(define.Krand(8, define.KC_RAND_KIND_ALL))
		var userList models.MMember
		var inviteCode int64
		tx.Model(new(models.MMember)).Where("invite_code=?", inviteCode1).Count(&inviteCode).Find(&userList)
		if inviteCode <= 0 {
			break
		}
		fmt.Println(i)
	}
	//插入数据
	var user models.MMember
	if appType == "weixintoutiao" {
		user.Nickname = "微信用户"
	} else if appType == "toutiao" {
		user.Nickname = "抖音用户"
	} else {
		user.Nickname = "微信用户"
	}
	user.Pwd = myPassword
	user.Headimg = "https://mjs-nbdz-com.oss-cn-hangzhou.aliyuncs.com/upload/video/20230901/202309011703090121.jpg"
	user.Isfreeze = 1
	user.InviteCode = inviteCode1
	user.Pid = parId.ID
	user.Levelid = 1
	user.Money = decimal.NewFromFloat(0)
	user.Available = 0
	user.CommunitySum = 0
	user.Platform = appType
	user.Score = 0
	user.Commission = decimal.NewFromFloat(0)
	user.Sex = "0"
	user.Wxopenid = OpenId
	user.Checkst = 0
	user.Createtime = int(time.Now().Unix())
	user.LastVisittime = int(time.Now().Unix())
	user.Aid = 1
	result := tx.Create(&user)
	if result.Error != nil {
		tx.Rollback()
		return 0, "", result.Error
	}
	err = models.RegisterGivest(tx, 1, user.ID)
	if err != nil {
		tx.Rollback()
		return 0, "", err
	}
	//注册成功
	return user.ID, user.InviteCode, nil
}
